<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.19"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Modbus cpp: Main Page</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectalign" style="padding-left: 0.5em;">
   <div id="projectname">Modbus cpp
   &#160;<span id="projectnumber">0.1</span>
   </div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.19 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
var searchBox = new SearchBox("searchBox", "search",false,'Search');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(function() {
  initMenu('',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
/* @license-end */</script>
<div id="main-nav"></div>
</div><!-- top -->
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div class="PageDoc"><div class="header">
  <div class="headertitle">
<div class="title">Modbus cpp Documentation</div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p><a class="anchor" id="md_README"></a></p><h1>Modbus library for modern c++</h1>
<p>Modbus library for high level frame manipulation with modern c++17/20.</p>
<p>Contains simple linux TCP and RTU implementation.</p>
<h1><a class="anchor" id="autotoc_md0"></a>
Contents</h1>
<ul>
<li><a href="#why">Why</a></li>
<li><a href="#important-concept">Important Concept</a></li>
<li><a href="#possibilities">Possibilities</a></li>
<li><a href="#status">Status</a></li>
<li><a href="#how-to-install-it-">Installation</a></li>
<li><a href="#api">Api</a></li>
</ul>
<h1><a class="anchor" id="autotoc_md1"></a>
Why</h1>
<p>When I was working on my last project and tried to find a good c++ Modbus library (other than Qt) I was unable to find it. That is why I have decided to share my own implementation of it.</p>
<h1><a class="anchor" id="autotoc_md2"></a>
Important Concept</h1>
<p>This library is <b>mainly</b> for providing Modbus logic, it doesnt aim to have best communiaction implementation. It gives user ability to create Modbus frames in high level api and convert them to raw bytes or show them as string. That is why <em>Modbus Core</em> is OS independent and can be eaisly used with other communication frameworks.</p>
<p>It does have communiaction module which is <b>enabled</b> by default, and works pretty well on linux.</p>
<h1><a class="anchor" id="autotoc_md3"></a>
Possibilities</h1>
<p>Quick example of what Modbus Core can do:</p>
<p>Code: </p><div class="fragment"><div class="line"> {c++}</div>
<div class="line">#include &lt;modbusRequest.hpp&gt;</div>
<div class="line"> </div>
<div class="line">// Create simple request</div>
<div class="line">MB::ModbusRequest request(1, MB::utils::ReadDiscreteOutputCoils, 100, 10);</div>
<div class="line"> </div>
<div class="line">std::cout &lt;&lt; &quot;Stringed Request: &quot; &lt;&lt; request.toString() &lt;&lt; std::endl;</div>
<div class="line"> </div>
<div class="line">std::cout &lt;&lt; &quot;Raw request:&quot; &lt;&lt; std::endl;</div>
<div class="line"> </div>
<div class="line">// Get raw represenatation for request</div>
<div class="line">std::vector&lt;uint8_t&gt; rawed = request.toRaw();</div>
<div class="line"> </div>
<div class="line">// Method for showing byte</div>
<div class="line">auto showByte = [](const uint8_t&amp; byte)</div>
<div class="line">{</div>
<div class="line">    std::cout &lt;&lt; &quot; 0x&quot; &lt;&lt; std::hex &lt;&lt; std::setw(2) &lt;&lt; std::setfill(&#39;0&#39;) &lt;&lt; static_cast&lt;int&gt;(byte);</div>
<div class="line">};</div>
<div class="line"> </div>
<div class="line">// Show all bytes</div>
<div class="line">std::for_each(rawed.begin(), rawed.end(), showByte);</div>
<div class="line">std::cout &lt;&lt; std::endl;</div>
<div class="line"> </div>
<div class="line">// Create CRC and pointer to its bytes</div>
<div class="line">uint16_t CRC = MB::utils::calculateCRC(rawed);</div>
<div class="line">auto CRCptr = reinterpret_cast&lt;uint8_t *&gt;(&amp;CRC);</div>
<div class="line"> </div>
<div class="line">// Show byted CRC for request</div>
<div class="line">std::cout &lt;&lt; &quot;CRC for the above code: &quot;;</div>
<div class="line">std::for_each(CRCptr, CRCptr + 2, showByte);</div>
<div class="line">std::cout &lt;&lt; std::endl;</div>
<div class="line"> </div>
<div class="line"> </div>
<div class="line">auto request1 = MB::ModbusRequest::fromRaw(rawed);</div>
<div class="line">std::cout &lt;&lt; &quot;Stringed Request 1 after rawed: &quot; &lt;&lt; request1.toString() &lt;&lt; std::endl;</div>
<div class="line"> </div>
<div class="line">// Add CRC to the end of raw request so that it can be loaded with CRC check</div>
<div class="line">rawed.insert(rawed.end() , CRCptr, CRCptr + 2);</div>
<div class="line">auto request2 = MB::ModbusRequest::fromRawCRC(rawed); // Throws on invalid CRC</div>
<div class="line">std::cout &lt;&lt; &quot;Stringed Request 2 after rawed: &quot; &lt;&lt; request2.toString() &lt;&lt; std::endl;</div>
</div><!-- fragment --><p>Output: </p><div class="fragment"><div class="line">Stringed Request: Read from output coils, from slave 1, starting from address 100, on 10 registers</div>
<div class="line">Raw request:</div>
<div class="line"> 0x01 0x01 0x00 0x64 0x00 0x0a</div>
<div class="line">CRC for the above code:  0xfd 0xd2</div>
<div class="line">Stringed Request 1 after rawed: Read from output coils, from slave 1, starting from address 100, on 10 registers</div>
<div class="line">Stringed Request 2 after rawed: Read from output coils, from slave 1, starting from address 100, on 10 registers</div>
</div><!-- fragment --><h1><a class="anchor" id="autotoc_md4"></a>
STATUS</h1>
<p>Currently Modbus Core is fully functional and (I belive) it doesn't have any bugs.</p>
<p>API for it is in progress.</p>
<p>Modbus Communication is working <em>currently</em> only for linux, it works well on TCP and Serial (tested on raspberry pi).</p>
<h1><a class="anchor" id="autotoc_md5"></a>
How to learn Modbus ?</h1>
<p>Just use <a href="http://www.simplymodbus.ca/FAQ.htm">Simply modbus</a>.</p>
<h1><a class="anchor" id="autotoc_md6"></a>
How to install it ?</h1>
<h3><a class="anchor" id="autotoc_md7"></a>
Using CMAKE and git</h3>
<p>First go to directory that will contain this library.</p>
<div class="fragment"><div class="line">git clone https://github.com/Mazurel/Modbus</div>
</div><!-- fragment --><p>Then add to your CMakeLists.txt </p><div class="fragment"><div class="line">add_subdirectory(Modbus)</div>
<div class="line">target_link_libraries(&lt;your exec/lib&gt; Modbus)</div>
</div><!-- fragment --><p>You should be able to use library.</p>
<p><b>NOTE</b> If you are on other os then gnu/linux you should disable communication part of modbus via cmake variable MODBUS_COMMUNICATION.</p>
<h1><a class="anchor" id="autotoc_md8"></a>
API</h1>
<p><a href="https://raw.githack.com/Mazurel/Modbus/master/docs/html/index.html">link</a></p>
<h2><a class="anchor" id="autotoc_md9"></a>
It is the best to use docs generated by doxygen</h2>
<p>You can read it in <a href="https://raw.githack.com/Mazurel/Modbus/master/docs/html/index.html">docs/html</a> or generate it yourself via: </p><div class="fragment"><div class="line">doxygen Doxyfile</div>
</div><!-- fragment --><h2><a class="anchor" id="autotoc_md10"></a>
The below API is not finished (propably wont be), it is preffered to use doxygen for code documentation.</h2>
<ul>
<li><a href="#enums">Enums</a></li>
<li><a href="#methods">Methods</a></li>
<li><a href="#classes">Classes</a></li>
</ul>
<h2><a class="anchor" id="autotoc_md11"></a>
Enums</h2>
<p>Below each enum there are all values of enum.</p><ul>
<li><p class="startli"><code><a class="el" href="namespaceMB_1_1utils.html#aa34c557c9bf4c6bfeb86aa16b398de55">MB::utils::MBErrorCode</a></code> - Enum that contains all the standard Modbus error Codes as well as Modbus library specific errors. ```c++ // Documentation modbus errors: IllegalFunction = 0x01 IllegalDataAddress = 0x02 IllegalDataValue = 0x03 SlaveDeviceFailure = 0x04 Acknowledge = 0x05 SlaveDeviceBusy = 0x06 NegativeAcknowledge = 0x07 MemoryParityError = 0x08 GatewayPathUnavailable = 0x10 GatewayTargetDeviceFailedToRespond = 0x11</p>
<p class="startli">// Custom modbus errors: ErrorCodeCRCError = 0b0111111 InvalidCRC = 0b01111110 InvalidByteOrder = 0b01111101 InvalidMessageID = 0b01111100 ProtocolError = 0b01111011 ConnectionClosed = 0b01111010 Timeout = 0b01111001 ``<code> -</code><a class="el" href="namespaceMB_1_1utils.html#aa8ebb89b73bf4d0e3485b6341a50f116" title="All modbus standard function codes + Undefined one.">MB::utils::MBFunctionCode&lt;tt&gt;</a>- Enum that contains all Modbus function codes. ``c++ // Reading functions ReadDiscreteOutputCoils = 0x01 ReadDiscreteInputContacts = 0x02 ReadAnalogOutputHoldingRegisters = 0x03 ReadAnalogInputRegisters = 0x04</p>
<p class="startli">// Single write functions WriteSingleDiscreteOutputCoil = 0x05 WriteSingleAnalogOutputRegister = 0x06</p>
<p class="startli">// Multiple write functions WriteMultipleDiscreteOutputCoils = 0x0F WriteMultipleAnalogOutputHoldingRegisters = 0x10</p>
<p class="startli">// Custom Undefined = 0x00 ``<code> -</code><a class="el" href="namespaceMB_1_1utils.html#a0b3590994f5ba26cd61929f5a394ab70" title="Simplified function types.">MB::utils::MBFunctionType&lt;tt&gt;</a>- Enum that contains function types. ``c++ Read WriteSingle WriteMultiple ``<code> -</code><a class="el" href="namespaceMB_1_1utils.html#a8098c5bcb6c33b219bafdee42334e260" title="Simplified register types.">MB::utils::MBFunctionRegisters&lt;tt&gt;</a>- Enum that contains all register types. ``c++ <br  />
 OutputCoils InputContacts HoldingRegisters InputRegisters ```</p>
</li>
</ul>
<h2><a class="anchor" id="autotoc_md12"></a>
Methods</h2>
<ul>
<li><code>bool <a class="el" href="namespaceMB_1_1utils.html#a7aa22230ea192f06612fbc809fca2335" title="Checks if error code is modbus standard error code.">MB::utils::isStandardErrorCode(MBErrorCode code)</a></code> - Returns true if specified code is a Modbus standard error code.</li>
<li><code>std::string <a class="el" href="namespaceMB_1_1utils.html#af467d314367c209ef830b2ae97393b6f" title="Converts Modbus error code to it&#39;s string representation.">MB::utils::mbErrorCodeToStr(MBErrorCode code)</a></code> - Returns stringed name of a specified Modbus error code. <br  />
</li>
<li><code>MBFunctionType <a class="el" href="namespaceMB_1_1utils.html#ab24a81a029cf6c4765eab5d74b7d8dff" title="Checks &quot;Function type&quot;, according to MBFunctionType.">MB::utils::functionType(const MBFunctionCode code)</a></code> - Get functions type based on function code.</li>
<li><code>MBFunctionRegisters <a class="el" href="namespaceMB_1_1utils.html#ad967d0ef18fecbc1a231143db3793991" title="Get register type based on function code.">MB::utils::functionRegister(const MBFunctionCode code)</a></code> - Get functions register based on function code.</li>
<li><code>uint16_t <a class="el" href="namespaceMB_1_1utils.html#a2057e90dfbefb2bc7cea23f6140d5a04" title="Create uint16_t from buffer of two bytes, ex. { 0x01, 0x02 } =&gt; 0x0102.">MB::utils::bigEndianConv(const uint8_t *buf)</a></code> - Creates uint16_t number from uint8_t buffer of two bytes (used when reading modbus frames).</li>
<li><p class="startli"><code>uint16_t <a class="el" href="namespaceMB_1_1utils.html#aa419ed339bbdacd4108fb5cc1cd14539" title="Calculates CRC.">MB::utils::calculateCRC(const uint8_t *buff, size_t len)</a></code></p>
<p class="startli"><code>uint16_t <a class="el" href="namespaceMB_1_1utils.html#aa419ed339bbdacd4108fb5cc1cd14539" title="Calculates CRC.">MB::utils::calculateCRC</a>(const std::vector&lt;uint8_t&gt;&amp; buffer)</code> - Pretty self explanatory. </p>
</li>
</ul>
<h2><a class="anchor" id="autotoc_md13"></a>
Classes</h2>
<blockquote class="doxtable">
<p>For each getter and setter field there is:</p>
<p>&lt;name&gt;() const - that gets the value</p>
<p>set&lt;Name&gt;(value) - that sets value </p>
</blockquote>
<h4><a class="anchor" id="autotoc_md14"></a>
ModbusException</h4>
<p>Its prupose is to represent Modbus exception, either frame or c++ exception</p>
<ul>
<li>Constructor:<ul>
<li><code>ModbusException(const std::vector&lt;uint8_t&gt;&amp; inputData, bool CRC = false);</code> - Creates ModbusException from raw bytes, with CRC check based on parameter.</li>
<li>`ModbusException(utils::MBErrorCode errorCode, uint8_t slaveId = 0xFF, utils::MBFunctionCode functionCode = utils::Undefined) noexcept : _slaveId(slaveId), _validSlave(true), _errorCode(errorCode), _functionCode(functionCode) {}` - Creates Modbus exception based on it's properties.</li>
</ul>
</li>
<li>Methods:<ul>
<li><code>static ModbusException::exist(const std::vector&lt;uint8_t&gt;&amp; inputData)</code> - Checks if there is exception in modbus frame.</li>
<li><code>std::string toString()</code> - Returns string representation of exception.</li>
<li><code>std::vector&lt;uint8_t&gt; toRaw()</code> - Retruns raw frame represenation of a excaption.</li>
</ul>
</li>
<li>Getters and setters:<ul>
<li>functionCode</li>
<li>slaveID</li>
</ul>
</li>
</ul>
<h4><a class="anchor" id="autotoc_md15"></a>
ModbusRequest</h4>
<p>Its purpose is to represent modbus request frame.</p>
<ul>
<li>Constructors:<ul>
<li><code>static ModbusRequest(std::vector&lt;uint8_t&gt; inputData, bool CRC = false)</code> - Creates Modbus request based on raw bytes and CRC boolean. If CRC is ON and the check fails constructor throws exception.</li>
<li><code>static ModbusRequest::fromRaw(const std::vector&lt;uint8_t&gt;&amp; inputData)</code> - Creates ModbusRequest from raw bytes.</li>
<li><code>static ModbusRequest::fromRawCRC(const std::vector&lt;uint8_t&gt;&amp; inputData)</code> - Creates ModbusRequest from raw bytes and checks CRC. When CRC is invalid throws InvalidCRC exception.</li>
<li>`ModbusRequest(uint8_t slaveId = 0, utils::MBFunctionCode functionCode = static_cast&lt;utils::MBFunctionCode&gt;(0), uint16_t address = 0, uint16_t registersNumber = 0, std::vector&lt;ModbusCell&gt; values = {})` - Self explanatory.</li>
</ul>
</li>
<li>Methods:<ul>
<li><code>std::string ModbusRequest::toString()</code> - Returns string representation of a request.</li>
<li><code>std::vector&lt;uint8_t&gt; ModbusRequest::toRaw()</code> - Converts ModbusRequest to raw bytes.</li>
<li><code><a class="el" href="namespaceMB_1_1utils.html#a0b3590994f5ba26cd61929f5a394ab70" title="Simplified function types.">MB::utils::MBFunctionType</a> functionType() const</code> - Gets function type for current function code.</li>
<li><code><a class="el" href="namespaceMB_1_1utils.html#a8098c5bcb6c33b219bafdee42334e260" title="Simplified register types.">MB::utils::MBFunctionRegisters</a> functionRegisters() const</code> - Gets function register for current function code.</li>
</ul>
</li>
<li>Getters and setters:<ul>
<li>slaveID</li>
<li>functionCode</li>
<li>registerAddress</li>
<li>numberOfRegisters</li>
<li>registerValues</li>
</ul>
</li>
</ul>
<h4><a class="anchor" id="autotoc_md16"></a>
ModbusResponse</h4>
<p>Its purpose is to represent response frame.</p>
<ul>
<li>Constructors:<ul>
<li><code>static ModbusResponse(std::vector&lt;uint8_t&gt; inputData, bool CRC = false)</code> - Creates Modbus response based on raw bytes and CRC boolean. If CRC is ON and the check fails constructor throws exception.</li>
<li><code>static ModbusResponse::fromRaw(const std::vector&lt;uint8_t&gt;&amp;)</code> - Creates ModbusResponse from raw bytes</li>
<li><code>static ModbusResponse::fromRawCRC(const std::vector&lt;uint8_t&gt;&amp;)</code> - Creates ModbusResponse from raw bytes and checks CRC. When CRC is invalid throws InvalidCRC exception.</li>
<li>`ModbusResponse(uint8_t slaveId = 0, utils::MBFunctionCode functionCode = 0x00, uint16_t address = 0, uint16_t registersNumber = 0, std::vector&lt;ModbusCell&gt; values = {})`<ul>
<li>Self explanatory constructor.</li>
</ul>
</li>
</ul>
</li>
<li>Methods:<ul>
<li><code>std::string toString()</code> - Returns ModbusResponse string representation.</li>
<li><code>std::vector&lt;uint8_t&gt; toRaw()</code> - Converts ModbusResponse to vector of raw bytes.</li>
<li><code>void from(const ModbusRequest&amp;)</code> - Fills ModbusResponse with the request. Needed if you want ModbusResponse to have all the data. This method is needed when you create object from raw.</li>
<li><code><a class="el" href="namespaceMB_1_1utils.html#a0b3590994f5ba26cd61929f5a394ab70" title="Simplified function types.">MB::utils::MBFunctionType</a> functionType() const</code> - Gets function type for current function code.</li>
<li><code><a class="el" href="namespaceMB_1_1utils.html#a8098c5bcb6c33b219bafdee42334e260" title="Simplified register types.">MB::utils::MBFunctionRegisters</a> functionRegisters() const</code> - Gets function register for current function code.</li>
</ul>
</li>
<li>Getters and setters:<ul>
<li>slaveID</li>
<li>functionCode</li>
<li>registerAddress</li>
<li>numberOfRegisters</li>
<li>registerValues </li>
</ul>
</li>
</ul>
</div></div><!-- PageDoc -->
</div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated by&#160;<a href="http://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.8.19
</small></address>
</body>
</html>
